package cfdt.common.jwt;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * JWT数据对象
 * 源码来自于CFCA无纸化，重构了JWT依赖源码
 */
public class JwtClaims {

    public static final String ISSUER = "iss";
    public static final String SUBJECT = "sub";
    public static final String AUDIENCE = "aud";
    public static final String EXPIRATION = "exp";
    public static final String NOT_BEFORE = "nbf";
    public static final String ISSUED_AT = "iat";
    public static final String ID = "jti";
    public static final String CLAIMS = "claimsMap";
    /**
     * 存放JWT参数
     */
    private final Map<String, Object> claimsMap = new LinkedHashMap<>(20);

    /**
     * 向claims映射中添加键值对
     *
     * @param key 键，不能为空
     * @param value 值，不能为空
     * @throws IllegalArgumentException 当key或value为空时抛出
     */
    public void put(String key, String value) {
        if (StrUtil.isEmpty(key)) {
            throw new IllegalArgumentException("key of Claims is null");
        } else if (StrUtil.isEmpty(value)) {
            throw new IllegalArgumentException("value of Claims is null");
        } else {
            this.claimsMap.put(key, value);
        }
    }

    /**
     * 根据键获取对应的值
     *
     * @param key 键，不能为空
     * @return 返回对应键的字符串值，如果键不存在或值为null则返回null
     * @throws IllegalArgumentException 当key为空时抛出此异常
     */
    public String get(String key) {
        if (StrUtil.isEmpty(key)) {
            throw new IllegalArgumentException("key of Claims is null");
        } else {
            Object value = this.claimsMap.get(key);
            return null != value ? String.valueOf(value) : null;
        }
    }

    /**
     * 将外部的claims映射批量添加到当前claims映射中
     *
     * @param externalClaims 外部的claims映射，不能为空
     * @throws IllegalArgumentException 当externalClaims为空或为空映射时抛出
     */
    public void putAll(Map<String, Object> externalClaims) {
        if (null != externalClaims && !externalClaims.isEmpty()) {
            this.claimsMap.putAll(externalClaims);
        } else {
            throw new IllegalArgumentException("putAll failed , externalClaims is null");
        }
    }

    /**
     * 设置JWT的subject(主题)声明
     *
     * @param subject 主题值，不能为空
     * @throws IllegalArgumentException 当subject为空时抛出
     */
    public void setSubject(String subject) {
        if (StrUtil.isEmpty(subject)) {
            throw new IllegalArgumentException("subject of Claims is null");
        } else {
            this.claimsMap.put("sub", subject);
        }
    }

    /**
     * 设置JWT的issuedAt(签发时间)声明
     *
     * @param date 签发时间，不能为空
     * @throws IllegalArgumentException 当date为空时抛出
     */
    public void setIssuedAt(Date date) {
        if (null == date) {
            throw new IllegalArgumentException("IssuedAt of Claims is null");
        } else {
            this.claimsMap.put("iat", DateUtil.format(date, DatePattern.PURE_DATETIME_MS_FORMAT));
        }
    }

    /**
     * 设置JWT的expiration(过期时间)声明
     *
     * @param date 过期时间，不能为空
     * @throws IllegalArgumentException 当date为空时抛出
     */
    public void setExpiration(Date date) {
        if (null == date) {
            throw new IllegalArgumentException("Expiration of Claims is null");
        } else {
            this.claimsMap.put("exp", DateUtil.format(date, DatePattern.PURE_DATETIME_MS_FORMAT));
        }
    }

    /**
     * 获取当前claims映射的只读视图
     *
     * @return 返回包含所有claims的映射
     */
    public Map<String, Object> getClaims() {
        return this.claimsMap;
    }

    /**
     * 获取当前claims映射的只读视图(别名方法)
     *
     * @return 返回包含所有claims的映射
     */
    public Map<String, Object> getClaimsMap() {
        return claimsMap;
    }

    /**
     * 使用提供的claims映射替换当前claims映射中的所有内容
     *
     * @param claims 新的claims映射，不能为空
     * @throws IllegalArgumentException 当claims为空或为空映射时抛出
     */
    public void setClaims(Map<String, Object> claims) {
        if (null != claims && !claims.isEmpty()) {
            this.claimsMap.putAll(claims);
        } else {
            throw new IllegalArgumentException("setClaims failed , claims is null");
        }
    }

    /**
     * 获取claims映射中的参数数量
     *
     * @return 返回claims映射的大小
     */
    public int getParamsSize() {
        return this.claimsMap.size();
    }


}
